package com.cong.security.browser;

import com.cong.security.core.code.SmsCodeFilter;
import com.cong.security.core.code.ValidateCodeFilter;
import com.cong.security.core.code.sms.SmsCodeAuthenticationSecurityConfig;
import com.cong.security.core.code.sms.SmsCodeSender;
import com.cong.security.core.constant.SecurityConstant;
import com.cong.security.core.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.sql.DataSource;

/**
 * @Description TODO
 * @Author single-聪
 * @Date 2020/1/7 18:00
 * @Version 1.0.1
 **/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SecurityProperties securityProperties;
    // 成功处理器
    @Autowired
    private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
    // 失败处理器
    @Autowired
    private AuthenticationFailureHandler myAuthenticationFailureHandler;
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        // 设置数据源
        jdbcTokenRepository.setDataSource(dataSource);
        // 初次建表，后续启动注释
//        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    @Autowired
    private DataSource dataSource;
    @Autowired
    private SmsCodeSender smsCodeSender;
    @Autowired
    private SpringSocialConfigurer mySocialSecurityConfig;
    // 短信登录
    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    @Autowired
    private LogoutSuccessHandler myLogoutSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
        validateCodeFilter.setMyAuthenticationFailureHandler(myAuthenticationFailureHandler);
        validateCodeFilter.setSecurityProperties(securityProperties);
        // 初始化方法
        validateCodeFilter.afterPropertiesSet();
        SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
        smsCodeFilter.setMyAuthenticationFailureHandler(myAuthenticationFailureHandler);
        smsCodeFilter.setSecurityProperties(securityProperties);
        // 短信验证码校验接口
        smsCodeFilter.setSmsCodeSender(smsCodeSender);
        // 初始化方法
        smsCodeFilter.afterPropertiesSet();
        // 使用表单登录进行身份认证
        http.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)// 短信验证码过滤器
                .addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)// 图形验证码过滤器加入链
                .apply(mySocialSecurityConfig)// 第三方登录配置
                .and().formLogin()
                .loginPage(SecurityConstant.DEFAULT_UNAUTHENTICATION_URL)// 自定义登录页面
                .loginProcessingUrl("/login")// 自定义用户名密码登录请求路径
                .successHandler(myAuthenticationSuccessHandler) // 自定义成功处理器
                .failureHandler(myAuthenticationFailureHandler)// 自定义失败处理器
                .and()
                .rememberMe().tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(3600)// 设置默认值3600S
                .userDetailsService(userDetailsService)// 登录接口
                .and()
                .logout()
                .logoutUrl("logout")// 退出接口
                .logoutSuccessHandler(myLogoutSuccessHandler)// 退出成功处理器
                .deleteCookies("JSESSIONID")// 从cookies中删除相关信息
                .and()
                .authorizeRequests()
                .antMatchers("/code/*", "/user/bind", securityProperties.getBrowser().getSignUpUrl(), SecurityConstant.DEFAULT_UNAUTHENTICATION_URL, securityProperties.getBrowser().getLoginPage()).permitAll() // 放开,防止反复重定向
                .anyRequest() // 任何请求
                .authenticated()// 需要身份认证
                .and()
                .csrf().disable()//跨站请求伪造
                .apply(smsCodeAuthenticationSecurityConfig);
    }
}
